package model

import (
	"encoding/json"
	"fmt"
	"github.com/google/go-cmp/cmp"
	"testing"

	"go.mongodb.org/mongo-driver/bson"
)

type (
	volume_configuration_suit struct {
		value    string
		expected VolumeConfiguration
	}
)

var (
	strValue            = "/tmp/a:/tmp/b"
	structVolumeGeneric = Volume{
		TypeVolume: "test",
		Source:     "/tmp/a",
		Target:     "/tmp/b",
		ReadOnly:   true,
		Tmpfs:      map[string]string{"/tmpfs/a": "/tmpfs/b"},
	}
)

func TestVolumeWrapper_JSON(t *testing.T) {
	TestJsonSuits(
		t,
		[]Suit{
			{&VolumeWrapper{}, "null"},
			{&VolumeWrapper{StrValue: &strValue}, "\"/tmp/a:/tmp/b\""},
			{&VolumeWrapper{VolumeValue: &structVolumeGeneric}, "{\"type\":\"test\",\"source\":\"/tmp/a\",\"target\":\"/tmp/b\",\"read_only\":true,\"tmpfs\":{\"/tmpfs/a\":\"/tmpfs/b\"}}"},
		}, func(bytes []byte) (interface{}, error) {
			var reverse VolumeWrapper
			err := json.Unmarshal(bytes, &reverse)

			return &reverse, err
		},
	)
}

func TestVolumeWrapper_BSON(t *testing.T) {
	TestBsonSuits(
		t,
		[]Suit{
			{&VolumeWrapper{}, "null"},
			{&VolumeWrapper{StrValue: &strValue}, "\"/tmp/a:/tmp/b\""},
			{&VolumeWrapper{VolumeValue: &structVolumeGeneric}, "{\"type\": \"test\",\"source\": \"/tmp/a\",\"target\": \"/tmp/b\",\"read_only\": true,\"tmpfs\": {\"/tmpfs/a\": \"/tmpfs/b\"}}"},
		},
		func(value bson.RawValue) (interface{}, error) {
			var reverse VolumeWrapper
			err := value.Unmarshal(&reverse)

			return &reverse, err
		},
	)
}

func TestVolumeConfiguration(t *testing.T) {
	suits := []volume_configuration_suit{
		{"/tmp/a:/tmp/b", VolumeConfiguration{VolumeSource: "/tmp/a", ContainerPath: "/tmp/b", ReadOnly: false}},
		{"data:/tmp/b", VolumeConfiguration{VolumeSource: "data", ContainerPath: "/tmp/b", ReadOnly: false}},
	}
	for i, suit := range suits {
		t.Run(fmt.Sprintf("scenario-%d", i), func(t *testing.T) {
			wrapper := VolumeWrapper{StrValue: &suit.value}
			actual, err := wrapper.ToVolumeConfiguration()
			if err != nil {
				t.Fatalf("error: %s", err)
			}

			equal := cmp.Equal(suit.expected, actual)
			if !equal {
				t.Fatalf("not equal:\n%s", cmp.Diff(suit.expected, actual))
			}
		})

	}
}
